package com.msb.mall.ware.service.impl;

import com.msb.common.dto.SkuHasStockDto;
import com.msb.common.exception.NoStockExecption;
import com.msb.common.utils.R;
import com.msb.common.vo.OrderItemVo;
import com.msb.common.vo.WareSkuLockVO;
import com.msb.mall.ware.feign.ProductFeignService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.msb.common.utils.PageUtils;
import com.msb.common.utils.Query;

import com.msb.mall.ware.dao.WareSkuDao;
import com.msb.mall.ware.entity.WareSkuEntity;
import com.msb.mall.ware.service.WareSkuService;
import org.springframework.util.StringUtils;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareSkuDao wareSkuDao;

    @Autowired
    private ProductFeignService productFeignService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //查询的条件
        QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<WareSkuEntity>();
        String skuId = (String) params.get("skuId");
        String wareId = (String) params.get("wareId");
        if (!StringUtils.isEmpty(skuId)){
            queryWrapper.eq("sku_id",skuId);
        }
        if (!StringUtils.isEmpty(wareId)){
            queryWrapper.eq("ware_id",wareId);
        }
        IPage<WareSkuEntity> page = this.page(
            new Query<WareSkuEntity>().getPage(params),
            queryWrapper
        );
        return new PageUtils(page);
    }

    /**
     * 入库操作
     * @param skuId
     * @param wareId
     * @param skuNum
     */
    @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {

        List<WareSkuEntity> list = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>()
                .eq("sku_id", skuId)
                .eq("ware_id", wareId));
        if (list == null || list.size() == 0){
            //如果没有 就新增商品库存记录
            WareSkuEntity entity = new WareSkuEntity();
            entity.setSkuId(skuId);
            entity.setWareId(wareId);
            entity.setStock(skuNum);
            entity.setStockLocked(0);
            //todo : 动态设置商品的名称
            try {
                // 动态的设置商品的名称
                R info = productFeignService.info(skuId); // 通过Feign远程调用商品服务的接口
                Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");
                if(info.getCode() == 0){
                    entity.setSkuName((String) data.get("skuName"));
                }
            }catch (Exception e){

            }
            //插入商品库存记录
            wareSkuDao.insert(entity);
        }else {
            //如果有 就更新库存
            wareSkuDao.addStock(skuId,wareId,skuNum);
        }
    }

    @Override
    public List<SkuHasStockDto> getSkusHasStock(List<Long> skuIds) {
        List<SkuHasStockDto> list = skuIds.stream().map(skuId -> {

            Long count = baseMapper.getSkuStock(skuId);
            if (count==null) {
                count = 0L;
            }
            SkuHasStockDto dto = new SkuHasStockDto();
            dto.setSkuId(skuId);
            dto.setHasStock(count > 0);
            return dto;
        }).collect(Collectors.toList());
        return list;
    }

    @Override
    public Boolean orderLockStock(WareSkuLockVO vo) {
        List<OrderItemVo> items = vo.getItems();
        // 首先找到具有库存的仓库
        List<SkuWareHasStock> collect = items.stream().map(item -> {
            SkuWareHasStock skuWareHasStock = new SkuWareHasStock();
            skuWareHasStock.setSkuId(item.getSkuId());
            List<WareSkuEntity> wareSkuEntities = this.baseMapper.listHashStock(item.getSkuId());
            skuWareHasStock.setWareSkuEntities(wareSkuEntities);
            skuWareHasStock.setNum(item.getCount());
            return skuWareHasStock;
        }).collect(Collectors.toList());
        System.out.println("collect = " + collect);
        //尝试锁定库存
        for (SkuWareHasStock skuWareHasStock : collect) {
            Long skuId = skuWareHasStock.getSkuId();
            List<WareSkuEntity> wareSkuEntities = skuWareHasStock.wareSkuEntities;
            if (wareSkuEntities == null || wareSkuEntities.size() <= 0){
                //当前商品没库存了
                throw new NoStockExecption(skuId);
            }
            // 当前需要锁定的商品的梳理
            Integer count = skuWareHasStock.getNum();
            Boolean skuStocked = false; //表示当前SkuId的库存锁定完成
            for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
                System.out.println("wareSkuEntity = " + wareSkuEntity);
                Integer canStock = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
                System.out.println("count = " + count);
                System.out.println("canStock = " + canStock);
                if (count <= canStock){
                    // 表示当前的skuId 的商品的数量小于等于 需要锁定的数量
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),count);
                    count = 0;
                    skuStocked = true;
                }else{
                    // 需要锁定的库存大于 可以锁定的库存 就按照已有的库存来锁定
                    Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),count);
                    count = count - canStock;
                }
                if (count <= 0){
                    break; //表示所有的商品都锁定了
                }
            }
            if (count > 0){
                // 说明库存没有锁定完
                throw new NoStockExecption(skuId);
            }
            if (skuStocked == false){
                // 表示上一个商品的没有锁定库存成功
                throw new NoStockExecption(skuId);
            }
        }
        return true;
    }

    @Data
    class SkuWareHasStock{
        private Long skuId;
        private Integer num;
        private List<WareSkuEntity> wareSkuEntities;
    }
}